package project;

import project.platform.Platform;

import java.io.IOException;
import java.util.*;

import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;

import project.Animal;


public class AnimalMain extends MIDlet implements CommandListener, Runnable {
    /** User interface command to exit the current application. */
    private final Command exitCommand = new Command("Exit", Command.EXIT, 2);

    /** User interface command to issue a request to get animals from servlet. */
    private final Command servletReceiveCommand = new Command("Receive from Servlet", Command.SCREEN, 1);

    /** User interface command to issue a request to send an animal to servlet. */
    private final Command servletSendCommand = new Command("Send to Servlet", Command.SCREEN, 1);
    
    /** User interface command to issue a request to send an animal by MMS. */
    private final Command mmsSendCommand = new Command("Send by MMS", Command.SCREEN, 1);
    
    /** User interface command to issue a request to receive an animal by MMS. */
	private Command mmsReceiveCommand = new Command("Receive by MMS", Command.SCREEN, 1);

    /** User interface command to choose a test. */
    private final Command chooseCommand = new Command("Choose", Command.SCREEN, 2);

    /** User interface command to confirm current operation. */
    private final Command okCommand = new Command("OK", Command.OK, 1);

    /** User interface command to abort current operation. */
    private final Command cancelCommand = new Command("Cancel", Command.CANCEL, 1);
    
    /** User interface command to store the animal received by MMS. */
    private final Command Store = new Command("Store", Command.SCREEN, 1);

    static final Command battleCommand = new Command("Battle" ,Command.SCREEN,3);
    static final Command createCommand = new Command("Create Animal" ,Command.SCREEN,3);
    static final Command deleteCommand = new Command("Delete Animal" ,Command.SCREEN,3);
    static final Command selectCommand = new Command("Select" ,Command.SCREEN,3);
    static final Command backCommand = new Command("Back", Command.BACK, 1);
	
    /** The current display object. */
    private Display display;
    
    List type;
    
    Form battleScreen;
    /** The animal to send */
    private Animal animalTest;

    /** Array of animals that could be sent. */
    private Vector testCases;

    /** User interface list for selection. */
    private List list,list1;

    /** Current command to process. */
    private Command currentCommand;

    /** The current command processing thread. */
    private Thread commandThread;
    
    /** The application-ID on which we send MMS messages */
    private String appID;

    /** Area where the user enters the phone number to send the message to */
    private TextField destinationField;

    /** Error message displayed when an invalid phone number is entered */
    private Alert errorMessageAlert;

    /** Alert that is displayed when a message is being sent */
    private Alert sendingMessageAlert;

    /** The screen used to prompt for the phone number to send the MMS to */
    private Form mmsSendScreen = null;
    
    /** The screen used to display the incoming MMS */
    private Form mmsReceiveScreen = null;
    Form inputName;
    Form input;
    Form inputIntell;
    Form inputstr;
    Form inputdex;
    Form inputOwner;
    
    /** Text Box to display messages on screen */
    private TextBox textBox;
    
    /** Boolean for if this is or is not the first run */
    private boolean firstTime;

	private Display dgDisplay;
	private AnimalAnimate hdCanvas;
	Form mainMenu;
	Form chooseInstr,choose;
	List menuStuff;
	//List type;
	Game game = new Game();
	int start = 0;
	TextField name,speed,intelligence,dexterity,strength,owner;
	int TypeAnimal;
	int IntelligenceAnimal;
	int SpeedAnimal;
	int DexterityAnimal;
	int StrengthAnimal;
	Alert splash;
	String attribute;
	
    /** Initialize the MIDlet with a handle to the current display */
    public AnimalMain() {
    	/* set up animal storage */
        this.testCases = new Vector();
        this.testCases.addElement(new Animal("Monkey1"));
        this.testCases.addElement(new Animal("Monkey2"));
        this.animalTest = (Animal) this.testCases.elementAt(0);

        /* set up menus */
        this.display = Display.getDisplay(this);
        this.firstTime = true;
        
        /* set up mms stuff */
        appID = getAppProperty("MMS-ApplicationID");

        mmsSendScreen = createSendForm();
        mmsReceiveScreen = createReceiveForm();

        errorMessageAlert = new Alert("MMS", null, null, AlertType.ERROR);
        errorMessageAlert.setTimeout(5000);

        sendingMessageAlert = new Alert("MMS", null, null, AlertType.INFO);
        sendingMessageAlert.setTimeout(1000);
        sendingMessageAlert.setCommandListener(this);
    }

    /** 
     * Create MMS send form. 
     * Takes in destination phone number.
     * @return Form for the sending of MMS messages.
     */
	private Form createSendForm() {
		Form mmsSendForm = new Form("New MMS");
        destinationField = new TextField("Destination Address: ", "mms://", 256, TextField.ANY);
        mmsSendForm.append(destinationField);
        mmsSendForm.addCommand(okCommand);
        mmsSendForm.addCommand(cancelCommand);
        mmsSendForm.setCommandListener(this);
        return mmsSendForm;
	}
	
	/** 
	 * Create MMS receive screen .
	 * Shows a "Receiving..." message during the act.
	 * @return Form for the receipt of MMS messages.
	 */
	private Form createReceiveForm() {
		Form mmsReceiveScreen = new Form("MMS Receive");
        mmsReceiveScreen.addCommand(cancelCommand);
        mmsReceiveScreen.addCommand(Store);
        mmsReceiveScreen.setCommandListener(this);
        mmsReceiveScreen.append("Receiving...");
        return mmsReceiveScreen;
	}

    /**
     * Debug output routine.
     * @param s string to be printed.
     */
    private static final void DEBUG(final String s) {
        if (true)
			System.out.println(s);
    }

    /**
     * Start creates the thread to do the timing.
     * It should return immediately to keep the dispatcher
     * from hanging.
     */
    public void startApp() {
    	
    	this.menu();
    	
    	/*
        if (this.firstTime) {
            this.mainScreen();
            this.firstTime = false;
        } else
			this.display.setCurrent(this.textBox);
    */
    }

    /**
     * Display the main screen.
     */
    void mainScreen() {
    	dgDisplay = Display.getDisplay(this); 
		this.testCases = new Vector();
		for(int i = 0; i < game.Animals.size();i++){
			this.testCases.addElement(game.Animals.elementAt(i).toString());
		}
        this.testCases.addElement(new Animal("Monkey2"));
        this.testCases.addElement(new Animal("Monkey4"));
        this.animalTest = (Animal)this.testCases.elementAt(0);

        /* set up menus */
        this.display = Display.getDisplay(this);
        
        /* set up mms stuff */
        appID = getAppProperty("MMS-ApplicationID");
        mmsSendScreen = createSendForm();
        mmsReceiveScreen = createReceiveForm();
        errorMessageAlert = new Alert("MMS", null, null, AlertType.ERROR);
        errorMessageAlert.setTimeout(5000);

        sendingMessageAlert = new Alert("MMS", null, null, AlertType.INFO);
        sendingMessageAlert.setTimeout(1000);
        sendingMessageAlert.setCommandListener(this);
              
		try{
			hdCanvas = new AnimalAnimate(this, "/owl1.gif");
			hdCanvas.start();
			setCommands(hdCanvas,false);
			hdCanvas.setCommandListener(this);
			dgDisplay.setCurrent(hdCanvas);
			
		}
			
		catch (IOException ioe) 
		{
			System.err.println("Problem loading image "+ioe);
		}

		//	Set newly created canvas as current canvas


    }

	public void getType(){
	  	type = new List("Animal Type",Choice.IMPLICIT);
	   	type.append("  Owl", null);
	   	type.append("  Ape", null);
		type.append("  Lion", null);
		type.append("  Bear", null);
		type.setCommandListener(this);
		type.addCommand(backCommand);
		type.addCommand(selectCommand);
		type.setTitle("Type Select");
		display.setCurrent(type); 
	}
	    
    public void getName(){
    	StringItem attributeItem1 = new StringItem ("Please enter a value for this Attribute\n", "A maximum of 9 points per attribute"); 
    	inputName = new Form("INPUT");
    	attribute = "Name";
    	name = new TextField("Please Enter a value: ","",10,TextField.ANY&TextField.ANY);
    	inputName.append("This is for Name");
    	inputName.append(attributeItem1);
    	inputName.append(name);
    	inputName.setCommandListener(this);
    	inputName.addCommand(backCommand);
    	inputName.addCommand(selectCommand);
    	//currentMenu = "name";
    	display.setCurrent(inputName);
    }
    public void getSpeed(){
    	StringItem attributeItem = new StringItem ("Please enter a value for this Attribute\n", "A maximum of 9 points per attribute"); 
    	input = new Form("INPUT");
    	attribute = "speed";
    	speed = new TextField("Please Enter a value: ","",1,TextField.ANY&TextField.NUMERIC);
    	input.append("This is for Speed");
    	input.append(attributeItem);
    	input.append(speed);
    	input.addCommand(backCommand);
    	input.addCommand(selectCommand);
    	input.setCommandListener(this);
    //	currentMenu = "speed";
    	display.setCurrent(input);
    }
    public void getIntelligence(){
    	StringItem attributeItem2 = new StringItem ("Please enter a value for this Attribute\n", "A maximum of 9 points per attribute"); 
		inputIntell = new Form("INPUT");
    	attribute = "Intelligence";
    	intelligence = new TextField("Please Enter a value: ","",1,TextField.ANY&TextField.NUMERIC);
    	inputIntell.append("This is for Intelligence");
    	inputIntell.append(attributeItem2);
    	inputIntell.append(intelligence);
    	inputIntell.setCommandListener(this);
    	inputIntell.addCommand(backCommand);
    	inputIntell.addCommand(selectCommand);
    //	currentMenu = "intelligence";
    	display.setCurrent(inputIntell);
    }

    public void getStrength(){
    	StringItem attributeItem4 = new StringItem ("Please enter a value for this Attribute\n", "A maximum of 9 points per attribute"); 
		inputstr = new Form("INPUT");
    	attribute = "Strength";
    	strength = new TextField("Please Enter a value: ","",1,TextField.ANY&TextField.NUMERIC);
    	inputstr.append("This is for Strength");
    	inputstr.append(attributeItem4);
    	inputstr.append(strength);
    	inputstr.addCommand(backCommand);
    	inputstr.addCommand(selectCommand);
    	inputstr.setCommandListener(this);
    	display.setCurrent(inputstr);
//    	currentMenu = "strength";
    }
    public void getDexterity(){
    	StringItem attributeItem5 = new StringItem ("Please enter a value for this Attribute\n", "A maximum of 9 points per attribute"); 
		inputdex = new Form("INPUT");
    	attribute = "Dexterity";
    	dexterity = new TextField("Please Enter a value: ","",1,TextField.ANY&TextField.NUMERIC);
    	inputdex.append("This is for Dexterity");
    	inputdex.append(attributeItem5);
    	inputdex.append(dexterity);
    	inputdex.addCommand(backCommand);
    	inputdex.addCommand(selectCommand);
    	inputdex.setCommandListener(this);
    	display.setCurrent(inputdex);
    }
    
    public void getOwner(){
    	StringItem attributeItem3 = new StringItem ("Please enter a value for this Attribute\n", "A maximum of 9 points per attribute"); 
		inputOwner = new Form("INPUT");
    	attribute = "Your Name";
    	owner = new TextField("Please Enter a value: ","",10,TextField.ANY&TextField.ANY);
    	inputOwner.append("Please enter your name");
    	inputOwner.append(attributeItem3);
    	inputOwner.append(owner);
    	inputOwner.addCommand(backCommand);
    	inputOwner.addCommand(selectCommand);
    	inputOwner.setCommandListener(this);
    	display.setCurrent(inputOwner);
    	System.err.print("here");
   
    }
    public void menu(){
    	menuStuff = new List("Menu",Choice.IMPLICIT);
		menuStuff.append("Play Game", null);
		menuStuff.append("Instructions", null);
		menuStuff.append("About", null);
		menuStuff.setCommandListener(this);
		menuStuff.addCommand(exitCommand);
		menuStuff.addCommand(selectCommand);
		menuStuff.setTitle("Animals Main Menu");
		display.setCurrent(this.menuStuff);
		//Image splashImage = Image.createImage("/splash.gif");
		//splash = new Alert("", "         2BA7 - Group 7 - Animals",splashImage,null);
		
	} 
	public void Instructions() {
        chooseInstr = new Form("Instructions for the Game");
        chooseInstr.setTicker(new Ticker("Testing List"));
        chooseInstr.addCommand(backCommand);
        chooseInstr.setCommandListener(this);
        StringItem versionItem = new StringItem ("How to: \n", "Here you go for the INSTRUCTIONS\n\nThe game is based on animals." +
        		"Using selected menu's you can create, battle and send animals which you've created to the other phones with this game." +
        		"The commands are very similar to various other games on mobile devices so they will be intuitive");
        chooseInstr.append(versionItem);
        display.setCurrent(chooseInstr);
        //currentMenu = "instructions"; 
   }

    public void about(){
        
        choose = new Form("About Us");
        choose.setTicker(new Ticker("\'Animals\' development team"));

      //  choose.addCommand(mainMenuCommand);
        choose.addCommand(backCommand);
        choose.setCommandListener(this);
        StringItem versionItem = new StringItem ("This Game was developed by :  \n", "Brendan Carroll \nJamie Daly\nChris LaPat\nPaul McGrath");
        choose.append(versionItem);
        
        display.setCurrent(choose);
        //currentMenu = "about"; 
   }
    
    /**
     * Display screen used to pick an Animal to use for sending.
     */
    void chooseScreen() {
        this.list = new List("Choose Animal", Choice.EXCLUSIVE);

        for (int i = 0; i < this.testCases.size(); i++)
			this.list.append(((Animal)this.testCases.elementAt(i)).toString(), null);

        this.setCommands(this.list, true);
        this.display.setCurrent(this.list);
    }
    
    void chooseBattle() { //test this properly
        this.list1 = new List("Choose Animal", Choice.MULTIPLE);

        for (int i = 0; i < this.testCases.size(); i++)
			this.list1.append(((Animal)this.testCases.elementAt(i)).toString(), null);

        this.setCommands(this.list1, true);
        this.display.setCurrent(this.list1);
    }

    /**
	 * Test the communications with the servlet.
	 * @param requestType type of request ("Send" or "Receive")
	 * @param a Animal to send (ignored if request is "Receive")
	 */
	private void testServlet(final String requestType, final Animal a) {
		boolean success = false;
		if (requestType == "Send")
			// first parameter should be taken in by dialog
			// second parameter should by set by user at first run
			success = Platform.sendToServer(a, "testuser", "testuser");
		else{
			// parameter should be set by user at first run
			final Object[] newTestCases = Platform.receiveFromServer("testuser");
			success = newTestCases!=null;
			if (success)
				addNewToStored(newTestCases);
		}
		String result = "";
		if (success)
			result =  "Operation completed successfully.";
		else
			result = "Operation failed.";
		this.textBox = new TextBox("Result", result, result.length(),0);
	    this.setCommands(this.textBox, false);
	    this.display.setCurrent(this.textBox);
	}

	/**
	 * Add new test cases to the vector where they are stored.
	 * Synchronized for thread-safety.
	 * @param newTestCases
	 */
	private synchronized void addNewToStored(final Object[] newTestCases) {
		//TestMidlet.DEBUG("Adding "+newTestCases.length+" new test cases.");
		for (int i = 0; i<newTestCases.length; i++){
			//TestMidlet.DEBUG("Adding: "+newTestCases[i].toString());
			this.testCases.addElement(newTestCases[i]);
		}
	}

    public void startBattle(Animal a ,Animal b){
    	battleScreen = new Form("BATTLE");
    	battleScreen.append(game.attackAnimals(a, b).toString());
    	battleScreen.append(game.fightAnimals("yooo", "SquirrelMan").toString());
    	battleScreen.setCommandListener(this);
    	battleScreen.addCommand(okCommand);
    	display.setCurrent(battleScreen);
    }

	/**
     * Set the funtion to perform based on commands selected.
     * @param d Displayable object
     * @param islist flag to indicate list processing
     */
    void setCommands(final Displayable d, final boolean islist) {
        if (islist)
			d.addCommand(this.okCommand);
		else {
            d.addCommand(this.exitCommand);
            d.addCommand(this.chooseCommand);
            d.addCommand(this.servletReceiveCommand);
            d.addCommand(this.servletSendCommand);
            d.addCommand(this.mmsSendCommand);
            d.addCommand(this.mmsReceiveCommand);
            d.addCommand(this.battleCommand);
            d.addCommand(this.createCommand);
         //   d.addCommand(this.deleteCommand);
		}
        d.setCommandListener(this);
    }

    /**
     * Pause signals the thread to stop by clearing the thread field.
     * If stopped before done with the iterations it will
     * be restarted from scratch later.
     */
    public void pauseApp() {
    }

    /**
     * Destroy must cleanup everything.  The thread is signaled
     * to stop and no result is produced.
     * @param unconditional Flag to indicate that forced shutdown
     * is requested
     */
    public void destroyApp(final boolean unconditional) {
    }

    /**
     * Respond to commands, including exit
     * @param c command to perform
     * @param s Screen displayable object
     */
    public void commandAction(final Command c, final Displayable s) {
        synchronized (this) {
            try {
            	if ((s == mmsSendScreen) && (c == okCommand)) 
            		Platform.sendByMMS(
            				this.destinationField.getString(), 
            				animalTest, 
            				sendingMessageAlert, 
            				errorMessageAlert, 
            				appID, 
            				display);
            	if ((s == mmsReceiveScreen) && (c == Store)){
            		this.addNewToStored(Platform.getMMS());
            		this.chooseScreen();

            	}else if ((s == this.type) && (c == this.selectCommand))
                	this.getName();
            	else if ((s == this.inputName) && (c == this.selectCommand))
                	this.getSpeed();
            	else if ((s == this.input) && (c == this.selectCommand))
            		this.getIntelligence();
            	else if ((s == this.inputIntell) && (c == this.selectCommand))
            		this.getStrength();
            	else if ((s == this.inputstr) && (c == this.selectCommand))
            		this.getDexterity();
            	else if ((s == this.inputdex) && (c == this.selectCommand))
            		this.getOwner();
            	else if ((s == this.inputOwner) && (c == this.selectCommand)){
            		Animal new1 = new Animal(Integer.parseInt(speed.getString()),Integer.parseInt(strength.getString()),
                			Integer.parseInt(dexterity.getString()),Integer.parseInt(intelligence.getString())
                			,name.getString(),owner.getString());
                	Object[] newTestCases = {new1};
                	addNewToStored(newTestCases);
                	this.mainScreen();
            	}else if ((s == this.choose) && (c == this.backCommand))
            		this.menu();
            	else if ((s == this.chooseInstr) && (c == this.backCommand))
            		this.menu();
            	else if ((s == this.inputOwner) && (c == this.backCommand))
            		this.getDexterity();
            	else if ((s == this.inputdex) && (c == this.backCommand))
            		this.getStrength();
            	else if ((s == this.inputstr) && (c == this.backCommand))
            		this.getIntelligence();
            	else if ((s == this.inputIntell) && (c == this.backCommand))
            		this.getSpeed();
            	else if ((s == this.input) && (c == this.backCommand))
            		this.getName();
            	else if ((s == this.inputName) && (c == this.backCommand))
            		this.menu();
            	else if ((s == this.battleScreen) && (c == this.okCommand))
            		this.mainScreen();
            	else if ((s == this.list1) && (c == this.okCommand)){
                    boolean[] chosen = new boolean[list1.size()];
                    this.list1.getSelectedFlags(chosen);
                    Animal fighter1 = null;
                    Animal fighter2 = null;
                    for (int i=0; i<this.list1.size(); i++){
                    	if (chosen[i] && fighter1 == null)
                    		fighter1 = (Animal) this.testCases.elementAt(i);
                    	else 
                    		fighter2 = (Animal) this.testCases.elementAt(i);
                    };
                    this.startBattle(fighter1, fighter2);
            	}

            	else if ((s == this.menuStuff) && (c == this.selectCommand)){
            	   List down = (List)display.getCurrent();
  	  	         	switch(down.getSelectedIndex()) {
  	  	         		case 0: this.getType();
  	  	         			break;
  	  	         		case 1: Instructions();
  	  	         			break;
  	  	         		case 2: about();
  	  	         			break;
  	  	         }
            	}
            
            }catch (Exception ex) {
                ex.printStackTrace();
            }
        	
            if (this.commandThread != null)
				// process only one command at a time
                return;

            this.currentCommand = c;
            this.commandThread = new Thread(this);
            this.commandThread.start();
        }
    }

    /**
     * Perform the current command set by the method commandAction.
     */
    public void run() {
    	
        if (this.currentCommand == this.exitCommand) {
            this.destroyApp(false);
            this.notifyDestroyed();
        } else if (this.currentCommand == this.servletReceiveCommand)
			this.testServlet("Receive", null);
		else if (this.currentCommand == this.servletSendCommand)
			this.testServlet("Send", this.animalTest);
		else if (this.currentCommand == this.chooseCommand)
			this.chooseScreen();
		else if (this.currentCommand == this.battleCommand)
			this.chooseBattle();
		else if (this.currentCommand == this.createCommand)
			this.getType();
		else if (this.currentCommand == this.mmsReceiveCommand){
			Platform.receiveMMS(appID,display,this.mmsReceiveScreen);
			this.display.setCurrent(this.mmsReceiveScreen);
		}
		else if (this.currentCommand == this.mmsSendCommand)
			this.display.setCurrent(mmsSendScreen);
		else if (this.currentCommand == this.okCommand) {
            final int i = this.list.getSelectedIndex();

            if (i >= 0)
				this.animalTest = (Animal) this.testCases.elementAt(i);

            this.mainScreen();
        } else if (this.currentCommand == this.cancelCommand)
			this.mainScreen();
        else if (this.currentCommand == Alert.DISMISS_COMMAND ) {
        	// Return from MMS sending.
        	mainScreen();
        }

        synchronized (this) {
            // signal that another command can be processed
            this.commandThread = null;
        }
    }
}
